package com.apes.fn.server.servicePlan.service.planNodeService;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.server.servicePlan.model.PriceApprovalReport;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.PriceApprovalReportRepository;
import com.apes.fn.server.servicePlan.repository.ServicePlanDao;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.query.SqlService;
import com.apes.framework.query.lib.PubToolUtil;
import com.apes.framework.rop.session.SimpleSession;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.party.model.PartyRole;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @program: apes-server
 * @description: 审核节点服务
 * @author: czs
 * @create: 2022-11-15 14:01
 **/
@Service("auditNodeService")
public class AuditNodeService extends DomainService {

    @Autowired
    private SqlService sqlService;
    @Autowired
    private ServicePlanDao servicePlanDao;
    @Autowired
    private PriceApprovalReportRepository priceApprovalReportRepository;
    @Autowired
    private ServicePlanItemRepository servicePlanItemRepository;

    public PageImpl<Map> priceAuditQuery(SimpleRequest request) throws ParseException{
        JSONObject jo = request.getJO();
        changeJsonToConditionField(request, jo);
        JSONArray array = getObjects(request,"fnPriceAudit.query4",true); //对数据进行查询
        JSONObject totalJson = null;
        if(array != null && array.size() != 0){
            totalJson = array.getJSONObject(0);
            array.remove(0);
        }
        Integer page = jo.getInteger("page");
        Integer size = jo.getInteger("size");
        Pageable pageable = PageRequest.of(page==null?0:page, size==null?2000:size);
        PageImpl<Map> pPage = new PageImpl(array, pageable, array == null ? 0 : totalJson.getJSONObject("SYS_PAGE").getInteger("Total"));  //总条数还没设置
//
        return pPage;
    }

    private void changeJsonToConditionField(SimpleRequest request, JSONObject jo) {
        if (jo.get("condition") instanceof JSONObject) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            JSONObject condition = (JSONObject) jo.get("condition");
            JSONArray result = new JSONArray();
            Iterator<String> iterator = condition.keySet().iterator();
            while (iterator.hasNext()) {
                String next = iterator.next();
                Object o = condition.get(next);

                //日期处理
                if (o==null||"".equals(o)){

                }else if (next.contains("DATE")){
                    if (o instanceof JSONArray){
                        JSONArray jsonArray = (JSONArray) o;
                        JSONArray dateArray = new JSONArray();
                        jsonArray.stream()
                                .map(s -> {
                                    try {
                                        String str = (String) s;
                                        str = str.replace("T"," ").replace(".","T").split("T")[0];
                                        return simpleDateFormat.parse(str);
                                    } catch (ParseException e) {
                                        e.printStackTrace();
                                    }
                                    return null;})
                                .filter(Objects::nonNull)
                                .sorted(Comparator.reverseOrder())
                                .forEach(date -> {
                                    JSONObject reultJson = new JSONObject();
                                    String s = dateArray.isEmpty() ? "LTE" : "GTE";
                                    long time = date.getTime();
                                    //因为是+8时区 所以减掉8小时
                                    long l = (time-28800000) % 86400000;
                                    boolean isFormat = l ==0|| l ==86399000;
                                    if (s.equals("GTE")&&!isFormat){
                                        time = time-l +28800000 ;
                                        date.setTime(time);
                                    }else if (s.equals("LTE")&&!isFormat){
                                        time = time-l +28800000 + 86399999  ;
                                        date.setTime(time);
                                    }
                                    reultJson.put("field",next);
                                    reultJson.put("operator", s);
                                    reultJson.put("value",date);
                                    reultJson.put("type","date");
                                    dateArray.add(reultJson);
                                });
                        result.addAll(dateArray);
                    }
                }else {
                    JSONObject reultJson = new JSONObject();
                    reultJson.put("field",next);
                    reultJson.put("operator","EQ");
                    reultJson.put("value",o);
                    result.add(reultJson);
                }

            }
            jo.put("condition",result);
            request.setData(jo);
        }
    }


    public PageImpl<Map> downloadQuery(SimpleRequest request) throws ParseException{
        JSONObject jo = request.getJO();
        changeJsonToConditionField(request, jo);
        JSONArray array = getObjects(request,jo.getString("queryid"),true); //对数据进行查询
        JSONObject totalJson = null;
        if(array != null && array.size() != 0){
            totalJson = array.getJSONObject(0);
            array.remove(0);
        }
        Integer page = jo.getInteger("page");
        Integer size = jo.getInteger("size");
        Pageable pageable = PageRequest.of(page==null?0:page, size==null?2000:size);
        PageImpl<Map> pPage = new PageImpl(array, pageable, array == null ? 0 : totalJson.getJSONObject("SYS_PAGE").getInteger("Total"));  //总条数还没设置
//
        return pPage;
    }
    /**
     * 查询商品清单
     *
     * @param request
     * @return
     */
    public Map priceAuditQueryProductList(SimpleRequest request) {
        JSONObject jsonObject = checkRequest(request);
        JSONArray array = servicePlanDao.queryProductList(jsonObject);
        return  packageReturnArray(array);
    }

    /**
     * 价格审核查看历史价格和有效价格文件
     *
     * @param request
     * @return
     */
    public Map priceAuditQueryReferTax(SimpleRequest request) {
        JSONObject jo = request.getJO();
        JSONArray array2 = servicePlanDao.queryValidT03(jo);
        return  mapper(
                "MIN_PRICE",jo.get("MIN_AMOUNT"),
                "MAX_PRICE",jo.get("MAX_AMOUNT"),
                "Items",array2
                );
    }

    /**
     * 解析前端参数
     *
     * @param request
     * @return
     */
    public JSONObject checkRequest(SimpleRequest request) {
        JSONObject condition = (JSONObject) request.get("condition");
        List<Map> filters = (List<Map>) condition.get("filters");
        JSONObject model = new JSONObject();
        filters.forEach(filter -> {
            model.put((String) filter.get("field"), filter.get("value"));
        });
        return model;
    }

    /***
     * 包装返回数据
     */
    private Map packageReturnArray(JSONArray array) {
        int size = array.size();
        return MapUtil.mapper(
                "content", array,
                "total", size,
                "size",  size
        );
    }

    private JSONArray getObjects(SimpleRequest re,String address,boolean page) {
        JSONArray array;
        try {
            com.apestech.framework.json.JSONObject json= PubToolUtil.getInput(re);
            //多余参数移除
            removeExtraParam(json);
            SimpleSession session = (SimpleSession)re.getRopRequestContext().getSession();
            if(session!= null) json.put("postId",session.getPostId());

            if(page) {
                Optional.ofNullable(json.get("page")).orElseThrow(()->new RuntimeException("分页查询，请传入page参数"));
                Optional.ofNullable(json.get("size")).orElseThrow(()->new RuntimeException("分页查询，请传入page参数"));
                if(json.getInteger("size") > 2000) new RuntimeException("分页条数不能大于2000");
                json.put("page",json.getInteger("page") + 1);
            }else{
                if(json.get("page") != null) json.remove("page");
                if(json.get("size") != null) json.remove("size");
            }
            array = tranTypeArray(Optional.ofNullable(sqlService.queryId(address,json)).orElseGet(()->new com.apestech.framework.json.JSONArray()));
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return array;
    }

    public void removeExtraParam(com.apestech.framework.json.JSONObject json){
        json.remove("customAction");
        json.remove("noSum");
        json.remove("queryid");
        json.remove("customQuery");
    }

    public static JSONArray tranTypeArray(com.apestech.framework.json.JSONArray array){
        return array.stream().map(item ->tranType((com.apestech.framework.json.JSONObject) item)).collect(Collectors.toCollection(JSONArray::new));
    }

    /**
     * 从frame json 转化为 阿里 json
     * @param json
     * @return
     */
    public static JSONObject tranType(com.apestech.framework.json.JSONObject json){
        return JSONObject.parseObject(JSON.toJSONString(json));
    }

    public void updatePriceApproval(ServicePlan servicePlan ,String wf_comments,String operator,SimpleRequest request){
        PartyRole person = getPerson(request);
        List<PriceApprovalReport> priceApprovalReportRepositoryAll = priceApprovalReportRepository.findAll(JpaDsl.toCriteria("planId", "EQ", servicePlan.getId(), "approvalResult", "EQ", null));
        Date date = new Date();
        for (PriceApprovalReport report : priceApprovalReportRepositoryAll) {
            report.setProcessDate(date);
            if ("1".equals(operator)){
                ServicePlanItem planItem = servicePlan.getServicePlanItems().stream().filter(servicePlanItem -> servicePlanItem.getId().equals(report.getPlanItemId())).findFirst().orElse(null);
                if (planItem!=null)report.setPftPriceUnit(planItem.getPftPriceUnit());
            }
            report.setProcessPerson(person);
            report.setApprovalRemark(wf_comments);
            report.setApprovalResult(operator);
            priceApprovalReportRepository.saveAndFlush(report);
        }
    }

    public void createPriceApprovalReport(ServicePlan servicePlan, SimpleRequest request) {
        Object person = getPerson(request);

        List<PriceApprovalReport> repetition = priceApprovalReportRepository.findAll(JpaDsl.toCriteria(
                "planId", "EQ", servicePlan.getId(), "approvalResult", "EQ", null));
        if (!repetition.isEmpty())return;

        List<ServicePlanItem> servicePlanItems = servicePlan.getServicePlanItems();
        Date date = new Date();
        for (ServicePlanItem servicePlanItem : servicePlanItems) {
            PriceApprovalReport priceApprovalReport = new PriceApprovalReport();
            BeanUtils.copyProperties(servicePlanItem,priceApprovalReport,"id");
            priceApprovalReport.setPlanId(servicePlan.getId());
            priceApprovalReport.setPlanItemId(servicePlanItem.getId());
            priceApprovalReport.setLimitLevel(findLimitLevel(servicePlanItem));
            priceApprovalReport.setRequestPerson((PartyRole) person);
            priceApprovalReport.setRequestDate(date);
            findLastApproval(priceApprovalReport);


            JSONArray array = servicePlanDao.queryHistoryPrice(new JSONObject(mapper(
                    "COMPANY_ID", servicePlan.getBelongDept().getCompany().getId(),
                    "PRODUCT_ID", servicePlanItem.getProduct().getId())));

            boolean b = array.size() > 0;
            JSONObject o = b ? (JSONObject) array.get(0) : new JSONObject();

            priceApprovalReport.setMaxAmount(o.getDoubleValue("MAX_PRICE"));
            priceApprovalReport.setMinAmount(o.getDoubleValue("MIN_PRICE"));

            priceApprovalReportRepository.saveAndFlush(priceApprovalReport);
        }

    }

    private String findLimitLevel(ServicePlanItem servicePlanItem) {
        if (servicePlanItem.isServiceState() && (servicePlanItem.getPftPriceUnit() <= 0 || servicePlanItem.getPriceUnit() <= 0))
            throw new RuntimeException("存在价格小于等于零的商品：" + servicePlanItem.getProduct().getName());
        double priceApprovalAmt = servicePlanItem.getPriceApprovalAmt();

        if (servicePlanItem.getPftPriceUnit() >= servicePlanItem.getClerkPriceLimit()) {
            if (priceApprovalAmt>0&& priceApprovalAmt<=servicePlanItem.getPftPriceUnit())return "5";
            return "5";  // 店助
        } else if (servicePlanItem.getPftPriceUnit() >= servicePlanItem.getShopOwnerPriceLimit()) {
            if (priceApprovalAmt>0&& priceApprovalAmt<=servicePlanItem.getPftPriceUnit())return "5";
            return "4";  // 店长
        } else if (servicePlanItem.getPftPriceUnit() >= servicePlanItem.getCsoPriceLimit()) {
            if (priceApprovalAmt>0&& priceApprovalAmt<=servicePlanItem.getPftPriceUnit())return "5";
            return "3";  // 销售总监
        } else if (servicePlanItem.getPftPriceUnit() >= servicePlanItem.getFloorPrice()) {
            if (priceApprovalAmt>0&& priceApprovalAmt<=servicePlanItem.getPftPriceUnit())return "5";
            return "2";  // 副总裁
        } else {
            if (priceApprovalAmt>0&& priceApprovalAmt<=servicePlanItem.getPftPriceUnit())return "5";
            return "1"; // 总裁
        }
    }

    private void findLastApproval(PriceApprovalReport priceApprovalReport) {
        PriceApprovalReport approvalReport = priceApprovalReportRepository.findAll(JpaDsl.toCriteria(
                "planItemId", "EQ", priceApprovalReport.getPlanItemId(),
                "product.id", "EQ", priceApprovalReport.getProduct().getId()), new Sort(Sort.Direction.DESC, "createDate")).stream().findFirst().orElse(null);
        if (approvalReport==null)return;
        priceApprovalReport.setLastApprovalId(approvalReport.getId());
        priceApprovalReport.setLastApprovalRemark(approvalReport.getApprovalRemark());
        priceApprovalReport.setLastApprovalResult(approvalReport.getApprovalResult());
        priceApprovalReport.setLastPftPriceUnit(approvalReport.getPftPriceUnit());
        priceApprovalReport.setApprovalNum(approvalReport.getApprovalNum()+1);

    }
    public List<PriceApprovalReport> findLastApproval(ServicePlan servicePlan) {
        List<PriceApprovalReport> approvalReport = priceApprovalReportRepository.findAll(JpaDsl.toCriteria(
                "planId", "EQ", servicePlan.getId(),
                "approvalResult","EQ",1), new Sort(Sort.Direction.DESC, "createDate"));
        if (approvalReport.isEmpty())return approvalReport;
        PriceApprovalReport priceApprovalReport = approvalReport.stream().max(Comparator.comparing(PriceApprovalReport::getApprovalNum)).get();
        return approvalReport.stream().filter(p -> p.getApprovalNum() == priceApprovalReport.getApprovalNum()).collect(Collectors.toList());
    }

    public List<PriceApprovalReport> findApprovalProduct(ServicePlan servicePlan) {
        List<PriceApprovalReport> approvalReport = priceApprovalReportRepository.findAll(JpaDsl.toCriteria(
                "planId", "EQ", servicePlan.getId(),
                "approvalResult","EQ",1), new Sort(Sort.Direction.DESC, "createDate"));
        if (approvalReport.isEmpty())return approvalReport;
        return approvalReport;
    }
    public List<PriceApprovalReport> findCurrentApproval(ServicePlan servicePlan) {
        List<PriceApprovalReport> approvalReport = priceApprovalReportRepository.findAll(JpaDsl.toCriteria(
                "planId", "EQ", servicePlan.getId()), new Sort(Sort.Direction.DESC, "createDate"));
        if (approvalReport.isEmpty())return approvalReport;
        PriceApprovalReport priceApprovalReport = approvalReport.stream().max(Comparator.comparing(PriceApprovalReport::getApprovalNum)).get();
        return approvalReport.stream().filter(p -> p.getApprovalNum() == priceApprovalReport.getApprovalNum()).collect(Collectors.toList());
    }

    public void insertAuditNodeServiceData(ServicePlan servicePlan) {
        List<PriceApprovalReport> lastApproval = findLastApproval(servicePlan);
        Map<String, List<PriceApprovalReport>> approvalMap = lastApproval.stream().collect(groupingBy(PriceApprovalReport::getPlanItemId));
        List<ServicePlanItem> servicePlanItems = servicePlan.getServicePlanItems();
        for (ServicePlanItem servicePlanItem : servicePlanItems) {
            double priceApprovalAmt = servicePlanItem.getPriceUnit();
            List<PriceApprovalReport> priceApprovalReports = approvalMap.get(servicePlanItem.getId());
            if (priceApprovalReports!=null&&priceApprovalReports.size()>0)priceApprovalAmt = priceApprovalReports.get(0).getPftPriceUnit();
            if (priceApprovalAmt<servicePlanItem.getPriceApprovalAmt())servicePlanItem.setPriceApprovalAmt(priceApprovalAmt);
        }

    }

    //    private void checkAndCancelPriceAudit(ServicePlan servicePlan) {
//        if (servicePlan.getSubmissionDate()!=null)return;
//        List<ServicePlanItem> collect = servicePlan.getServicePlanItems().stream().filter(ServicePlanItem::isPriceAudit).collect(Collectors.toList());
//        if (collect.isEmpty())return;
//        //获取任务编码
//        //crm.customComplain.getAllProcess
//        //{\"finished\":\"0\",\"startDate\":null,\"endDate\":null,\"id\":\"FW1001230200400\"}
//        // 查询主数据
//        com.apestech.framework.json.JSONArray array =
//                sqlService.queryId("oa.queryAllProcess", new com.apestech.framework.json.JSONObject(mapper("finished", 0, "id", servicePlan.getId())));
////        JSONObject taskId = this.invoke("crm.customComplain.getAllProcess", );
//        if (array.isEmpty())return;
//
//        String taskid = array.get(0).getString("TASKID");
//        Map taskMap = mapper("taskId", taskid, "changeSignFlag", true, "wfFlag", true, "OAInterface", true);
//        //找任务节点
//        //wf.getTaskByTaskId
//        //{\"taskId\":\"19060055\",\"changeSignFlag\":true,\"wfFlag\":true,\"OAInterface\":true}
////        Map task = this.invoke("wf.getTaskByTaskId", taskMap);
//
//        //执行拒绝
//        //wf.executeTask
//        //
//        Map mapped = MapUtil.mapped(servicePlan);
//        mapped.putAll(taskMap);
//        mapped.putAll(mapper(
//                "carbonCopy",mapper(),
//                "wf_carbonCopy",new JSONArray(),
//
//                "wfTaskId",taskid,
//                "wf_variable_wf_state","0",
//                "wf_comments","方案终止自动拒绝此业务"));
//        Object cancel = this.invoke("wf.executeTask",new JSONObject(mapped));
//        servicePlan = servicePlanRepository.findOne(servicePlan.getId());
//    }
}
